﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Net.Http;
using System.Web;
using System.Web.Mvc;
using Hangfire;
using Newtonsoft.Json;
using WSPay.Alipay;
using WSPay.Application;
using WSPay.Common;
using WSPay.Common.Log;
using WSPay.Core.DTO;
using WSPay.Domain;

namespace WSPay.Web.Controllers
{
    /// <summary>
    /// 支付宝支付
    /// </summary>
    public class PaymentController : Controller
    {
        public IPaymentService PaymentService
        { get;
            private set;
        }

        public PaymentController(IPaymentService paymentService)
        {
            this.PaymentService = paymentService;
        }
        public ActionResult Test(PaymentDto dto) {
            PaymentService.NoticePay("P070025915983");
            return View(dto);
            
        }
        /// <summary>
        /// 创建订单
        /// </summary>
        /// <returns></returns>
        public ActionResult CreateOrder(PaymentDto dto)
        {
            try
            {
                NLogLogger nlog = new NLogLogger();
                nlog.Info("支付订单创建：" + JsonConvert.SerializeObject(dto));
                var result = PaymentService.CreatePayment(dto);
                return Json(result, JsonRequestBehavior.AllowGet);
            }
            catch (Exception e)
            {
                return Json(e.Message,JsonRequestBehavior.AllowGet);
            }          
        }

        #region 手机

        private string GetPaySign(PaymentOrder payOrder) {
            var noticeUrl = Url.AbsoluteAction("PayNoticeMobile", "Payment");
            var ruturnUrl = string.Empty;// Url.AbsoluteAction("RuturnUrl", "Payment");
            Dictionary<string, string> sParaTemp = new Dictionary<string, string>();
            sParaTemp.Add("service", Config.mobileService);
            sParaTemp.Add("partner", Config.partner);
            sParaTemp.Add("seller_id", Config.partner);
            sParaTemp.Add("_input_charset", Config.input_charset.ToUpper());
            sParaTemp.Add("payment_type", Config.payment_type);
            sParaTemp.Add("notify_url", noticeUrl);
            sParaTemp.Add("return_url", ruturnUrl);
           sParaTemp.Add("anti_phishing_key", Config.anti_phishing_key);
            //sParaTemp.Add("exter_invoke_ip", Config.exter_invoke_ip);
            sParaTemp.Add("out_trade_no", payOrder.OrderId);
            sParaTemp.Add("show_url", ruturnUrl);
            sParaTemp.Add("subject", payOrder.OrderInfo);
            sParaTemp.Add("total_fee", payOrder.PayAmount.ToString("0.00"));
            //sParaTemp.Add("total_fee", "0.01");
            sParaTemp.Add("body", "商品详情");
            //包含签名的字典
            var sign = AlipayCore.RsaSign(sParaTemp);
            var signLink = AlipaySignature.GetSignContent(sParaTemp);
           // sParaTemp.Add("sign", HttpUtility.UrlEncode(signPara));
            //sParaTemp.Add("sign_type", "RSA");
           // string signLink = AlipaySignature.GetSignContent(sParaTemp);
            //signLink += "&sign=" + HttpUtility.UrlEncode(sign);
            signLink += "&sign=\"" + HttpUtility.UrlEncode(sign) +"\"" ;
            signLink += "&sign_type=\"RSA\"";
            return signLink;
        }
        /// <summary>
        /// 创建支付订单并返回支付签名
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public ActionResult CreateOrderAndGetSign(PaymentDto dto)
        {
            try
            {
                var payOrder = PaymentService.GetPaymentOrderBuyOrder(dto.BuyOrderId);
                if (payOrder != null) {
                    var sign = GetPaySign(payOrder);
                    return Json(new { errorCode = 0, message = "创建签名成功", data = sign }, JsonRequestBehavior.AllowGet);
                }
                NLogLogger nlog = new NLogLogger();
                nlog.Info("支付订单创建：" + JsonConvert.SerializeObject(dto));
                var result = PaymentService.CreatePayment(dto);
              
                if (result == WSBPayMessageDTO.Code0000) {
                    payOrder = PaymentService.GetPaymentOrderBuyOrder(dto.BuyOrderId);
                    var sign = GetPaySign(payOrder);
                    return Json(new {errorCode = 0, message = "创建签名成功" , data = sign }, JsonRequestBehavior.AllowGet);
                }

                return Json(new { errorCode = -1,message ="创建订单失败" }, JsonRequestBehavior.AllowGet);
            }
            catch (Exception e)
            {
                return Json(new { errorCode = -1,message = e.Message }, JsonRequestBehavior.AllowGet);
            }
        }


        #endregion
        // GET: Payment
        public ActionResult Pay(string orderId) {
            try
            {
                var noticeUrl = Url.AbsoluteAction("PayNotice", "Payment");
                var ruturnUrl = Url.AbsoluteAction("RuturnUrl", "Payment");

                //var noticeUrl = Url.AbsoluteAction("PayNoticeMobile", "Payment");
                //var ruturnUrl = Url.AbsoluteAction("PayNoticeMobile", "Payment");
                var payOrder = PaymentService.GetPaymentOrderBuyOrder(orderId);
                 SortedDictionary<string, string> sParaTemp = new SortedDictionary<string, string>();
                sParaTemp.Add("service", Config.service);
                sParaTemp.Add("partner", Config.partner);
                sParaTemp.Add("seller_id", Config.seller_id);
                sParaTemp.Add("_input_charset", Config.input_charset.ToUpper());
                sParaTemp.Add("payment_type", Config.payment_type);
                sParaTemp.Add("notify_url", noticeUrl);
                sParaTemp.Add("return_url", ruturnUrl);
                sParaTemp.Add("anti_phishing_key", Config.anti_phishing_key);
                //sParaTemp.Add("exter_invoke_ip", Config.exter_invoke_ip);
                sParaTemp.Add("out_trade_no", payOrder.OrderId);
                sParaTemp.Add("subject", payOrder.OrderInfo);
                sParaTemp.Add("total_fee", payOrder.PayAmount.ToString("0.00"));
                //sParaTemp.Add("total_fee", "0.01");
                sParaTemp.Add("body", "1212122");
                AlipaySubmit.BuildRequest(sParaTemp, "POST", "确认");
                return Content("");
            }
            catch (Exception e)
            {
                throw new ApplicationException(e.Message);
            }
        }
        public ActionResult WapPay(string orderId)
        {
            try
            {
                var noticeUrl = Url.AbsoluteAction("PayNotice", "Payment");
                var ruturnUrl = Url.AbsoluteAction("RuturnUrl", "Payment");

                //var noticeUrl = Url.AbsoluteAction("PayNoticeMobile", "Payment");
                //var ruturnUrl = Url.AbsoluteAction("PayNoticeMobile", "Payment");
                var payOrder = PaymentService.GetPaymentOrderBuyOrder(orderId);
                SortedDictionary<string, string> sParaTemp = new SortedDictionary<string, string>();
                sParaTemp.Add("service", Config.mobileService);
                sParaTemp.Add("partner", Config.partner);
                sParaTemp.Add("seller_id", Config.seller_id);
                sParaTemp.Add("_input_charset", Config.input_charset.ToUpper());
                sParaTemp.Add("payment_type", Config.payment_type);
                sParaTemp.Add("notify_url", noticeUrl);
                sParaTemp.Add("return_url", ruturnUrl);
                sParaTemp.Add("anti_phishing_key", Config.anti_phishing_key);
                //sParaTemp.Add("exter_invoke_ip", Config.exter_invoke_ip);
                sParaTemp.Add("out_trade_no", payOrder.OrderId);
                sParaTemp.Add("subject", payOrder.OrderInfo);
                sParaTemp.Add("total_fee", payOrder.PayAmount.ToString("0.00"));
                //sParaTemp.Add("total_fee", "0.01");
                //sParaTemp.Add("body", "1212122");
                AlipaySubmit.BuildRequest(sParaTemp, "POST", "确认");
                return Content("");
            }
            catch (Exception e)
            {
                throw new ApplicationException(e.Message);
            }
        }
        /// <summary>
        /// 同步通知
        /// </summary>
        /// <returns></returns>
        public ActionResult RuturnUrl()
        {
            string buyer_email = Request.Params["buyer_email"];
            string buyer_id = Request.Params["buyer_id"];
            string is_success = Request.Params["is_success"];
            string trade_status = Request.Params["trade_status"];
            NLogLogger nlog = new NLogLogger();
            nlog.Info("支付宝电商同步通知数据：" +(is_success));
                AlipayNotify aliNotify = new AlipayNotify();
                    string out_trade_no = Request.Params["out_trade_no"];
                    //支付宝交易号
                    string trade_no = Request.Params["trade_no"];
                    //交易状态
                  
                    var order = PaymentService.GetPaymentOrder(out_trade_no);
                    if (trade_status == "TRADE_FINISHED")
                    {
                        PaymentService.FailurePay(order.ID, trade_no);
                        return Json("fail");
                    }
                    else if (trade_status == "TRADE_SUCCESS")//支付成功
                    {
                        var key = PaymentService.GetMd5Key(order.ClientID);
                        var sp = "|";
                        var signString = order.ClientID + sp +
                                         key + sp +
                                         order.BuyOrderId + sp +
                                         order.OrderId + sp +
                                         order.State + sp +
                                         order.PayAmount.ToString("0.00") + sp +
                                         order.UserID + sp;

                        var sign = signString.Hash();
                        PaymentService.SuccessPay(order.ID, trade_no, Request.Params["buyer_email"], Request.Params["buyer_id"]);
                        var returnUrl = order.RuturnUrl+"";
                        if (order.RuturnUrl.Contains("?"))
                        {
                            returnUrl = order.RuturnUrl + "&OrderId=" + order.OrderId + "&PayerID=" + order.UserID +
                                        "&BuyOrderId=" + order.BuyOrderId
                                        + "&ClientID=" + order.ClientID +
                                        "&State=" + (order.State == PaymentState.Completed ? "success" : "fail") +
                                        "&OrderMoney=" + order.PayAmount.ToString("0.00") +
                                        "&AliAcount=" + order.AliPayAccount +
                                        "&AliId=" + order.AliPayId +
                                        "&Sign=" + sign;
                        }
                        else
                        {
                            returnUrl = order.RuturnUrl + "?OrderId=" + order.OrderId + "&PayerID=" + order.UserID +
                                        "&PayerID="
                                        + order.UserID + "&BuyOrderId=" + order.BuyOrderId
                                        + "&ClientID=" + order.ClientID +
                                        "&State=" + (order.State == PaymentState.Completed ? "success" : "fail") +
                                        "&OrderMoney=" + order.PayAmount.ToString("0.00") +
                                        "&AliAcount=" + order.AliPayAccount +
                                        "&AliId=" + order.AliPayId +
                                        "&Sign=" + sign;
                        }
                        return Redirect(returnUrl);
                    }
                    return Redirect("");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public ActionResult PayNotice()
        {
            SortedDictionary<string, string> sPara = GetRequestPost();
            NLogLogger nlog = new NLogLogger();
            nlog.Info("支付宝电商通知数据：" + JsonConvert.SerializeObject(sPara));
            if (sPara.Count > 0)//判断是否有带返回参数
            {
                AlipayNotify aliNotify = new AlipayNotify();
                bool verifyResult = aliNotify.Verify(sPara, Request.Form["notify_id"], Request.Form["sign"]);

                if (verifyResult)//验证成功
                {
                    string out_trade_no = Request.Form["out_trade_no"];
                    //支付宝交易号
                    string trade_no = Request.Form["trade_no"];
                    //交易状态
                    string trade_status = Request.Form["trade_status"];
                    var order = PaymentService.GetPaymentOrder(out_trade_no);
                    if (Request.Form["trade_status"] == "TRADE_FINISHED")
                    {
                        PaymentService.FailurePay(order.ID, trade_no);
                        return Json("fail");
                    }
                    else if (Request.Form["trade_status"] == "TRADE_SUCCESS")//支付成功
                    {
                        PaymentService.SuccessPay(order.ID, trade_no,Request.Form["buyer_email"],Request.Form["buyer_id"]);
                    }
                    return Json("success",JsonRequestBehavior.AllowGet);  //请不要修改或删除
                }
                else//验证失败
                {
                    return Json("fail", JsonRequestBehavior.AllowGet);
                }
            }
            else
            {
                return Json("无通知参数", JsonRequestBehavior.AllowGet);
            }
        }
        /// <summary>
        /// 用于支付成功但未通知到平台时,手动通知,请谨慎使用
        /// </summary>
        /// <param name="orderId">支付订单 订单id</param>
        /// <returns></returns>
        public ActionResult NormalNoticeToPlat(string orderId) {
            PaymentService.NoticePay(orderId);
            return Content("true");
        }

        public ActionResult PayNoticeMobile()
        {
            SortedDictionary<string, string> sPara = GetRequestPost();
            NLogLogger nlog = new NLogLogger();
            nlog.Info("支付宝电商通知数据：" + JsonConvert.SerializeObject(sPara));
            if (sPara.Count > 0)//判断是否有带返回参数
            {
                AlipayNotify aliNotify = new AlipayNotify();
                bool verifyResult = aliNotify.VerifyRsa(sPara, Request.Form["notify_id"], Request.Form["sign"]);

                if (verifyResult)//验证成功
                {
                    string out_trade_no = Request.Form["out_trade_no"];
                    //支付宝交易号
                    string trade_no = Request.Form["trade_no"];
                    //交易状态
                    string trade_status = Request.Form["trade_status"];
                    var order = PaymentService.GetPaymentOrder(out_trade_no);
                    if (Request.Form["trade_status"] == "TRADE_FINISHED")
                    {
                        PaymentService.FailurePay(order.ID, trade_no);
                        return Json("fail");
                    }
                    else if (Request.Form["trade_status"] == "TRADE_SUCCESS")//支付成功
                    {
                        PaymentService.SuccessPay(order.ID, trade_no, Request.Form["buyer_email"], Request.Form["buyer_id"]);
                    }
                    return Json("success", JsonRequestBehavior.AllowGet);  //请不要修改或删除
                }
                else//验证失败
                {
                    return Json("fail", JsonRequestBehavior.AllowGet);
                }
            }
            else
            {
                return Json("无通知参数", JsonRequestBehavior.AllowGet);
            }
        }
        /// <summary>
        /// 获取支付宝POST过来通知消息，并以“参数名=参数值”的形式组成数组
        /// </summary>
        /// <returns>request回来的信息组成的数组</returns>
        public SortedDictionary<string, string> GetRequestPost()
        {
            int i = 0;
            SortedDictionary<string, string> sArray = new SortedDictionary<string, string>();
            NameValueCollection coll;
            //Load Form variables into NameValueCollection variable.
            coll = Request.Form;

            // Get names of all forms into a string array.
            String[] requestItem = coll.AllKeys;

            for (i = 0; i < requestItem.Length; i++)
            {
                sArray.Add(requestItem[i], Request.Form[requestItem[i]]);
            }

            return sArray;
        }

    }
}